home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / misc / math / cp42.lha / cp42source.lha / drawview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-01  |  27.9 KB  |  1,285 lines

  1. #include "cp.h"
  2.  
  3. #define SIZETIC  5  /* size major tik in pixels */
  4. #define BOXOFF   10  /* add to filename box size */
  5. #define TIKCOLOR 2  /* color for tiks */
  6. #define BORDER   20 /* size between filename boxes */
  7.  
  8. struct RastPort *rp;
  9. struct ViewPort *vp;
  10.  
  11. struct World wd;
  12. struct CurView cv;
  13.  
  14. WORD WIDTH;
  15. WORD HEIGHT;
  16. WORD OFFSET;
  17.  
  18. WORD xoff;
  19. WORD yoff;
  20.  
  21. LONG precision = 2L;
  22.  
  23. /* Draw everything if full is TRUE autoscale */
  24.  
  25. void DrawView ( BOOL full )
  26. {
  27.  
  28.       vp = &(Scr-> ViewPort); /* Always reinit since could be new screen */
  29.       rp = PlotWindowWnd-> RPort;
  30.  
  31.     if (cv.xmin>=cv.xmax||cv.ymin>=cv.ymax)    FindWorld ();
  32.  
  33.      if( !(IsListEmpty(SetList)))
  34.        {
  35.  
  36.           if( full ) FindWorld ();
  37.     
  38.         if (! HandlePlotWindowIDCMP()) Death(0);
  39.  
  40.           SetAPen(rp,1);
  41.  
  42.           OFFSET = rp->Font->tf_YSize + 2 * BORDER + Scr-> BarHeight;
  43.           HEIGHT = PlotWindowWnd-> Height - OFFSET - ( CPANEL ? 4 : 3 ) * GADHEIGHT;
  44.  
  45.           yoff = OFFSET + HEIGHT;
  46.  
  47.           xoff = rp-> Font-> tf_XSize * 6 + BORDER + SIZETIC;
  48.  
  49.           DrawFileNameBoxes( yoff - HEIGHT);
  50.  
  51.           if ( WIDTH < BORDER || HEIGHT < BORDER ) Death(20);
  52.  
  53.           DrawColorBox( xoff , yoff, WIDTH, HEIGHT, 14);
  54.  
  55.           XAxis();
  56.           YAxis();
  57.           LabelTitle();
  58.           
  59.           DrawAllSets ();
  60.  
  61.           if ( sym ) SymAllSets();
  62.           if ( grid ) Grid();
  63.        }
  64.      else
  65.          Erase( TRUE );
  66. }
  67.  
  68. /* Draw all sets in SetList */
  69.  
  70. void DrawAllSets ()
  71. {
  72. WORD p = 4;
  73. struct Set *node;
  74.  
  75.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  76.        {
  77.  
  78.           SetAPen(rp,min(p,lastcolor));
  79.  
  80.           DrawSet ( node-> FirstPoint );
  81.  
  82.           p++;
  83.  
  84.           if ( p > lastcolor - 2 ) p = 4;
  85.  
  86.              if(! HandlePlotWindowIDCMP())    Death(5);
  87.  
  88.        }
  89. }
  90.  
  91. /* Draw symbols on all sets */
  92.  
  93. void SymAllSets ()
  94. {
  95. struct Set *node;
  96.  
  97.      SetDrMd( rp, JAM2);
  98.  
  99.      if (depth > 2)
  100.           SetAPen(rp,15);
  101.      else
  102.           SetAPen(rp,1);
  103.  
  104.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  105.        {
  106.  
  107.           SymSet ( node-> FirstPoint );
  108.  
  109.              if(! HandlePlotWindowIDCMP())    Death(5);
  110.  
  111.        }
  112. }
  113.  
  114. /* Adjust view so all data sets show */
  115.  
  116. void FindWorld ()
  117. {
  118. struct Set *node;
  119.  
  120.      node = (struct Set *)SetList-> lh_Head;
  121.  
  122.      wd.xmax = node-> xmax;
  123.      wd.xmin = node-> xmin;
  124.      wd.ymax = node-> ymax;
  125.      wd.ymin = node-> ymin;
  126.  
  127.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  128.        {
  129.  
  130.           wd.xmax = max( wd.xmax, node-> xmax);
  131.           wd.xmin = min( wd.xmin, node-> xmin);
  132.           wd.ymax = max( wd.ymax, node-> ymax);
  133.           wd.ymin = min( wd.ymin, node-> ymin);
  134.  
  135.        }
  136.  
  137.      cv.xmax = wd.xmax;
  138.      cv.xmin = wd.xmin;
  139.      cv.ymax = wd.ymax;
  140.      cv.ymin = wd.ymin;
  141.  
  142.      wd.xdelta = wd.xmax - wd.xmin;
  143.      wd.ydelta = wd.ymax - wd.ymin;
  144.  
  145.      cv.xdelta = wd.xdelta;
  146.      cv.ydelta= wd.ydelta;
  147. }
  148.  
  149. /* Draw one set */
  150.  
  151. void DrawSet ( struct Point *ThisPoint )
  152. {
  153. LONG qx, qy;
  154. LONG le, te, re, be;
  155.  
  156. struct Rectangle rect;
  157. struct Region *new_region;
  158. struct Region *old_region;
  159.  
  160.      rect.MinX = xoff;
  161.      rect.MaxX = xoff + WIDTH;
  162.      rect.MinY = yoff - HEIGHT;
  163.      rect.MaxY = yoff;
  164.  
  165.      le = PlotWindowWnd-> LeftEdge;
  166.      te = PlotWindowWnd-> TopEdge;
  167.      re = PlotWindowWnd-> LeftEdge + PlotWindowWnd-> Width;
  168.      be = PlotWindowWnd-> TopEdge + PlotWindowWnd-> Height;
  169.  
  170.      if ( ! (new_region = NewRegion())) return;
  171.  
  172.      if ( ! (OrRectRegion( new_region, &rect))) return;
  173.  
  174.      if (( old_region = InstallClipRegion( PlotWindowWnd-> WLayer, new_region ))) return;
  175.  
  176.      qx = ScaleX( ThisPoint-> xval);
  177.      qy = ScaleY( ThisPoint-> yval);
  178.  
  179.      if ( qx < le ) qx = le;
  180.      if ( qx > re ) qx = re;
  181.      if ( qy < te ) qy = te;
  182.      if ( qy > be ) qy = be;
  183.  
  184.      Move ( rp, qx, qy );
  185.  
  186.      do
  187.        {
  188.  
  189.           ThisPoint = ThisPoint-> NextPoint;
  190.  
  191.           qx = ScaleX( ThisPoint-> xval);
  192.  
  193.           /* need to change if not time sampled data */
  194.           if ( qx < le ) continue;
  195.           if ( qx > re && RealTime ) break;
  196.  
  197.           qy = ScaleY( ThisPoint-> yval);
  198.  
  199.           if ( qy < te ) qy = te;
  200.           if ( qy > be ) qy = be;
  201.  
  202.           Draw ( rp, qx, qy);
  203.  
  204.        } while ( ThisPoint-> NextPoint );
  205.  
  206.      new_region = InstallClipRegion(PlotWindowWnd->WLayer, old_region);
  207.  
  208.      DisposeRegion(new_region);
  209. }
  210.  
  211. /* draw symbols on one set */
  212.  
  213. void SymSet ( struct Point *ThisPoint )
  214. {
  215. LONG qx, qy;
  216. WORD dx, dy;
  217. BOOL clip;
  218.  
  219.      dx = xoff + WIDTH;
  220.      dy = yoff - HEIGHT;
  221.  
  222.      do {
  223.  
  224.  
  225.           clip = FALSE;
  226.  
  227.           qx = ScaleX( ThisPoint-> xval);
  228.           qy = ScaleY( ThisPoint-> yval);
  229.  
  230.           if ( qx < xoff )
  231.             {
  232.                qx = xoff;
  233.                clip = TRUE;
  234.             }
  235.           else if ( qx > dx )
  236.             {
  237.                qx = dx;
  238.                clip = TRUE;
  239.             }
  240.           if ( qy > yoff )
  241.             {
  242.                qy = yoff;
  243.                clip = TRUE;
  244.             }
  245.           else if ( qy < dy )
  246.             {
  247.                qy = dy;
  248.                clip = TRUE;
  249.             }
  250.  
  251.           if ( !clip )
  252.             {
  253.                Move ( rp, qx - 1, qy + 1);
  254.                Draw ( rp, qx + 1, qy - 1);
  255.                Move ( rp, qx + 1, qy + 1);
  256.                Draw ( rp, qx - 1, qy - 1);
  257.             }
  258.  
  259.           ThisPoint = ThisPoint-> NextPoint;
  260.  
  261.      } while ( ThisPoint );
  262. }
  263.  
  264. /* Draw recessed bevel box filled with color */
  265.  
  266. void DrawColorBox ( WORD xs ,WORD ys , WORD xw ,WORD yh, WORD color)
  267. {
  268.  
  269.      SetAPen( rp, (MONO ? 0 : color));
  270.  
  271.      RectFill( rp, xs, ys - yh - 1, xs + xw, ys + 1 );
  272.  
  273.      DrawBevelBox( rp, xs - 2, ys - yh - 1 , xw + 5, yh + 4, GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
  274. }
  275.  
  276.  
  277. /* Draw Color boxes with filenames in them */
  278.  
  279. WORD DrawFileNameBoxes( WORD ys)
  280. {
  281. struct Set *node;
  282. struct TextExtent txex;
  283. WORD p = 4, h = 0, w = 0, xs, ns = 0;
  284.  
  285.  
  286.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  287.        {
  288.           TextExtent( rp, node-> fn, strlen( node-> fn ), &txex);
  289.  
  290.           w = max( w, txex.te_Width);
  291.           h = max( h, txex.te_Height);
  292.  
  293.           ns++;
  294.        }
  295.  
  296.      w += BOXOFF;
  297.      h += BOXOFF;
  298.  
  299.      SetBPen( rp, 1);
  300.  
  301.      if ( ns > 1 )
  302.           xs = PlotWindowWnd-> Width - w - BORDER;
  303.      else
  304.        {
  305.           xs = ( PlotWindowWnd-> Width / 2 - w / 2);
  306.           ys = (WORD)(txex.te_Height * 1.5);
  307.        }
  308.  
  309.      WIDTH = PlotWindowWnd-> Width - (ns > 1 ? w + 2 * BORDER : xoff) - xoff; /* if only one set fnbox on top so width = windowwidth - 2*xoff */
  310.  
  311.     Erase(FALSE); /* need to erase before drawing fnboxes but could not get calc width till now */
  312.     
  313.     if (NOFNAME) return((WORD)xoff);
  314.  
  315.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  316.        {
  317.           SetAPen( rp, p);
  318.  
  319.           ys += h;
  320.  
  321.           TextExtent( rp, node-> fn, strlen( node-> fn ), &txex);
  322.  
  323.           if ( ns>1 || MONO == FALSE ) DrawColorBox( xs , ys, w, h, p );
  324.  
  325.           SetDrMd( rp, (JAM2 | INVERSVID));
  326.  
  327.           Move ( rp, xs + w/2 - txex.te_Width/2 , ys - BOXOFF / 2 );
  328.           Text( rp, node-> fn, strlen( node-> fn));
  329.  
  330.           ys += BORDER;
  331.  
  332.           SetDrMd( rp, JAM2);
  333.  
  334.           p++;
  335.           if ( p > lastcolor - 2 ) p = 4;
  336.        }
  337.  
  338.      return (WORD)( ns > 1 ? w + 2 * BORDER : xoff );
  339. }
  340.  
  341. /* Adjust xmin and xmax to even nubers and draw tiks with text */
  342.  
  343. void XAxis()
  344. {
  345.      LOGX ? logXAxis() : linXAxis();
  346. }
  347.  
  348. /* Adjust ymin and ymax to even nubers and draw tiks with text */
  349.  
  350. void YAxis()
  351. {
  352.      LOGY ? logYAxis() : linYAxis();
  353. }
  354.  
  355. void logXAxis()
  356. {
  357. LONG j, k, l;
  358. double q, r;
  359. struct TextExtent txex;
  360.  
  361.      /* Cant do negative log scale set lin */
  362.  
  363.      if( cv.xmin <= 0.0 )
  364.        {
  365.           SetWindowTitles( PlotWindowWnd, NULL, "Cant do LOG  X value <= zero" );
  366.           LOGX = FALSE;
  367.           linXAxis();
  368.           return;
  369.        }
  370.  
  371.      j = (LONG) log10( cv.xmin );
  372.      if( log10( cv.xmin ) <= 0.0 ) j-- ;
  373.      cv.xmin = pow( 10.0, (double)j );
  374.  
  375.      k = (LONG) log10( cv.xmax );
  376.      if( log10( cv.xmax ) > 0.0 ) k++ ;
  377.      cv.xmax = pow( 10.0, (double)k );
  378.  
  379.      cv.xdec = k - j;
  380.  
  381.      cv.xmode = -1;
  382.  
  383.      cv.xdelta = cv.xmax - cv.xmin;
  384.  
  385.      cv.xfact = 1;
  386.  
  387.     if (strlen(XLAB))
  388.       {    
  389.           TextExtent( rp, XLAB, strlen( XLAB ), &txex);
  390.  
  391.           SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  392.           SetBPen( rp, 0);
  393.  
  394.           Move ( rp, xoff + WIDTH/2 - txex.te_Width/2, yoff + 2 * GADHEIGHT);
  395.           Text( rp, XLAB, strlen( XLAB ));
  396.  
  397.       }
  398.  
  399.      for( q = cv.xmin ; q < cv.xmax; j++)
  400.        {
  401.           ticX( q, TRUE);
  402.           for( l = 2; l < 10; l++)
  403.             {
  404.                r = q * l;
  405.                if( r > cv.xmax ) break;
  406.                ticX( r, FALSE);
  407.             }
  408.           q = pow( 10.0, (double)j );
  409.        }
  410.  
  411.      ticX( cv.xmax, TRUE);
  412. }
  413.  
  414. void logYAxis()
  415. {
  416. LONG j, k, l;
  417. double q, r;
  418.  
  419.      /* Cant do negative log scale set lin */
  420.  
  421.      if( cv.ymin <= 0.0 )
  422.        {
  423.  
  424.           SetWindowTitles( PlotWindowWnd, NULL, "Cant do LOG  Y value <= zero" );
  425.  
  426.           LOGY = FALSE;
  427.           linYAxis();
  428.           return;
  429.        }
  430.  
  431.      if (YLAB) LabelY(YLAB);
  432.  
  433.      j = (LONG) log10( cv.ymin );
  434.      if( log10( cv.ymin ) <= 0.0 ) j-- ;
  435.      cv.ymin = pow( 10.0, (double)j );
  436.  
  437.      k = (LONG) log10( cv.ymax );
  438.      if( log10( cv.ymax ) > 0.0 ) k++ ;
  439.      cv.ymax = pow( 10.0, (double)k );
  440.  
  441.      cv.ydec = k - j;
  442.  
  443.      cv.ymode = -1;
  444.  
  445.      cv.ydelta = cv.ymax - cv.ymin;
  446.  
  447.      cv.yfact = 1;
  448.  
  449.      for( q = cv.ymin ; q < cv.ymax; j++)
  450.        {
  451.           ticY( q, TRUE);
  452.           for( l = 2; l < 10; l++)
  453.             {
  454.                r = q * l;
  455.                if( r > cv.ymax ) break;
  456.                ticY( r, FALSE);
  457.             }
  458.           q = pow( 10.0, (double)j );
  459.        }
  460.  
  461.      ticY( cv.ymax, TRUE);
  462. }
  463.  
  464. void linXAxis()
  465. {
  466. double a, p;
  467. LONG b;
  468. WORD k;
  469. UBYTE s[32], t[128];
  470. struct TextExtent txex;
  471.  
  472.      /* if x all the same value kluge */
  473.  
  474.      if ( cv.xmax == cv.xmin )
  475.        {
  476.           if ( cv.xmax == 0.0 ) cv.xmax = 1.0;
  477.           cv.xmax *= 1.01;
  478.           cv.xmin *= 0.99;
  479.        }
  480.  
  481.      /* end kluge */
  482.  
  483.      /* Calculate X View */
  484.  
  485.      cv.xtik = cv.xsubt = cv.xmode = cv.xprec = 0.0;
  486.  
  487.      tik( cv.xmin, cv.xmax, &cv.xtik, &cv.xsubt, &cv.xmode, &cv.xprec);
  488.  
  489.      a = cv.xmin / cv.xtik;
  490.      Round ( &a );
  491.      b = (LONG)a;
  492.      if ( a < 0 && b != a ) b--;
  493.      cv.xmin = cv.xtik * b;
  494.  
  495.      a = cv.xmax / cv.xtik;
  496.      Round ( &a );
  497.      b = (LONG)a;
  498.      if ( a > 0 && b != a ) b++;
  499.      cv.xmax = cv.xtik * b;
  500.  
  501.      cv.xdelta = cv.xmax - cv.xmin;
  502.  
  503.      SetDrMd( rp, JAM1);
  504.  
  505.     if ( XLAB) strcpy( t, XLAB);
  506.     else       strcpy(t,"");
  507.  
  508.      if ( cv.xmode )
  509.        {
  510.           CalcMode ( cv.xdelta , &cv.xfact );
  511.           sprintf( s, "x %.0le", cv.xfact);
  512.           E2xTen( s );
  513.         
  514.         if (XLAB)
  515.           {
  516.               strcat( t,"  ");
  517.               strcat( t, s);
  518.           }
  519.         else strcpy( t, s);
  520.        }
  521.  
  522.     if (strlen(t))
  523.       {    
  524.           TextExtent( rp, t, strlen( t ), &txex);
  525.  
  526.           SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  527.  
  528.           Move ( rp, xoff + WIDTH/2 - txex.te_Width/2, yoff + 2 * GADHEIGHT);
  529.           Text( rp, t, strlen( t ));
  530.  
  531.       }
  532.  
  533.      /* Draw Tick Marks */
  534.  
  535.      a = p = cv.xmin;
  536.      do
  537.        {
  538.           ticX( a, TRUE );
  539.           a += cv.xtik;
  540.           for ( k = 1; k <= cv.xsubt && p <= cv.xmax; k++)
  541.             {
  542.                ticX( p, FALSE);
  543.                p = a - k * cv.xtik / cv.xsubt;
  544.             }
  545.        } while ( p < cv.xmax );
  546.  
  547.      ticX( cv.xmax, TRUE);
  548. }
  549.  
  550. void linYAxis()
  551. {
  552. double a, p;
  553. LONG b;
  554. WORD k;
  555. UBYTE s[32], t[128];
  556.  
  557.      /* if y all the same value kluge */
  558.  
  559.      if ( cv.ymax == cv.ymin )
  560.        {
  561.           if ( cv.ymax == 0.0 ) cv.ymax = 1.0;
  562.           cv.ymax *= 1.01;
  563.           cv.ymin *= 0.99;
  564.        }
  565.  
  566.      /* end kluge */
  567.  
  568.      /* Calculate Y View */
  569.  
  570.      cv.ytik = cv.ysubt = cv.ymode = cv.yprec = 0.0;
  571.  
  572.      tik( cv.ymin, cv.ymax, &cv.ytik, &cv.ysubt, &cv.ymode, &cv.yprec);
  573.  
  574.      a = cv.ymin / cv.ytik;
  575.      Round ( &a );
  576.      b = (LONG)a;
  577.      if ( a < 0 && b != a ) b--;
  578.      cv.ymin = cv.ytik * b;
  579.  
  580.      a = cv.ymax / cv.ytik;
  581.      Round ( &a );
  582.      b = (LONG)a;
  583.      if ( a > 0 && b != a ) b++;
  584.      cv.ymax = cv.ytik * b;
  585.  
  586.      cv.ydelta = cv.ymax - cv.ymin;
  587.  
  588.  
  589.      SetDrMd( rp, JAM1);
  590.  
  591.     if ( YLAB) strcpy( t, YLAB);
  592.     else       strcpy(t,"");
  593.  
  594.  
  595.      if ( cv.ymode )
  596.        {
  597.           CalcMode ( cv.ydelta , &cv.yfact );
  598.  
  599.           sprintf( s, "%.0le", cv.yfact);
  600.           E2xTen( s );
  601.  
  602.         if (YLAB)
  603.           {
  604.               strcat( t,"  ");
  605.               strcat( t, s);
  606.           }
  607.         else strcpy( t, s);
  608.  
  609.  
  610.        }
  611.  
  612.     if (strlen(t))  LabelY(t);
  613.  
  614.      /* Draw Tick Marks */
  615.  
  616.      a = p = cv.ymin;
  617.      do
  618.        {
  619.           ticY( a , TRUE);
  620.           a += cv.ytik;
  621.           for ( k = 1; k <= cv.ysubt && p <= cv.ymax; k++)
  622.             {
  623.                ticY( p, FALSE);
  624.                p = a - k * cv.ytik / cv.ysubt;
  625.             }
  626.        } while ( p < cv.ymax );
  627.  
  628.      ticY( cv.ymax, TRUE);
  629. }
  630.  
  631. /* Y label text needs to be rotated 90 degrees */
  632.  
  633. void LabelY(UBYTE *lab)
  634. {
  635. struct TextExtent txex;
  636.  
  637.      TextExtent( rp, lab, strlen( lab ), &txex);
  638.      
  639.      SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  640.  
  641.     Move(rp,(SHORT)(txex.te_Height*1.5), yoff - HEIGHT/2 + txex.te_Width/2);
  642.  
  643.     VertText(rp,lab,strlen(lab));
  644. }
  645.  
  646. void LabelTitle()
  647. {
  648. struct TextExtent txex;
  649.     
  650.     if (strlen(TITLE))
  651.       {
  652.           TextExtent( rp, TITLE, strlen( TITLE ), &txex);
  653.  
  654.           SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  655.  
  656.           Move ( rp, xoff + WIDTH/2 - txex.te_Width/2, PlotWindowWnd-> TopEdge + 1);
  657.           Text( rp, TITLE, strlen( TITLE ));
  658.        }
  659. }
  660.  
  661. void Grid()
  662. {
  663.      if (! IsListEmpty(SetList))
  664.        {
  665.          LOGX ? logXGrid() : linXGrid() ;
  666.          LOGY ? logYGrid() : linYGrid() ;
  667.        }
  668. }
  669.  
  670. void logXGrid()
  671. {
  672. double q;
  673. double j, k;
  674. LONG x;
  675.  
  676.      SetDrMd( rp, COMPLEMENT);
  677.      SetDrPt( rp, 0x3333);
  678.  
  679.      j = log10( cv.xmin ) + 1.0;
  680.      k = log10( cv.xmax );
  681.  
  682.      for( j; j < k; j += 1.0)
  683.        {
  684.           q = pow( 10.0, (double)j );
  685.           x = ScaleX( q );
  686.           if ( x < xoff + WIDTH - 1 )
  687.             {
  688.                Move( rp, x, yoff );
  689.                Draw( rp, x, yoff - HEIGHT );
  690.             }
  691.        }
  692.  
  693.      SetDrPt( rp, 0xFFFF);
  694. }
  695.  
  696.  
  697. void logYGrid()
  698. {
  699. double q;
  700. double j, k;
  701. LONG y;
  702.  
  703.      SetDrMd( rp, COMPLEMENT);
  704.      SetDrPt( rp, 0x3333);
  705.  
  706.      j = log10( cv.ymin ) + 1.0;
  707.      k = log10( cv.ymax );
  708.  
  709.      for( j; j < k; j += 1.0)
  710.        {
  711.           q = pow( 10.0, (double)j );
  712.           y = ScaleY( q );
  713.           if ( y > yoff - HEIGHT + 1 )
  714.             {
  715.                Move( rp, xoff, y );
  716.                Draw( rp, xoff + WIDTH, y );
  717.             }
  718.        }
  719.  
  720.      SetDrPt( rp, 0xFFFF);
  721. }
  722.  
  723. void linXGrid()
  724. {
  725. double a;
  726. WORD x;
  727.  
  728.      SetDrMd( rp, COMPLEMENT);
  729.      SetDrPt( rp, 0x3333);
  730.  
  731.      a = cv.xmin;
  732.  
  733.      while ( a  < cv.xmax - cv.xtik )
  734.        {
  735.           a += cv.xtik;
  736.           x = ScaleX( (double)a );
  737.           if ( x < xoff + WIDTH - 1 )
  738.             {
  739.                Move( rp, x, yoff);
  740.                Draw( rp, x, yoff - HEIGHT);
  741.             }
  742.        }
  743.  
  744.      SetDrPt( rp, 0xFFFF);
  745. }
  746.  
  747. void linYGrid()
  748. {
  749. double a;
  750. WORD y;
  751.  
  752.      SetDrMd( rp, COMPLEMENT);
  753.      SetDrPt( rp, 0x3333);
  754.  
  755.      a = cv.ymin;
  756.  
  757.      while ( a < cv.ymax - cv.ytik )
  758.        {
  759.           a += cv.ytik;
  760.           y = ScaleY( (double)a );
  761.           if ( y > yoff - HEIGHT + 1 )
  762.             {
  763.                Move( rp, xoff, y );
  764.                Draw( rp, xoff + WIDTH, y );
  765.             }
  766.        }
  767.  
  768.      SetDrPt( rp, 0xFFFF);
  769. }
  770.  
  771. /* Color entire window with pen zero then refresh gadgets if control panel on*/
  772.  
  773. void Erase( BOOL all )
  774. {
  775. struct Rectangle frect;
  776. struct Rectangle drect;
  777. struct Region *new_region;
  778. struct Region *old_region;
  779.  
  780.  
  781.      SetDrMd( rp, JAM2);
  782.  
  783.     if ( !(IsListEmpty(SetList)) || ! all )
  784.       {
  785.          frect.MinX = 0;
  786.          frect.MaxX = PlotWindowWnd-> Width;
  787.          frect.MinY = 0;
  788.          frect.MaxY = PlotWindowWnd-> Height;
  789.  
  790.          drect.MinX = xoff;
  791.          drect.MaxX = xoff + WIDTH;
  792.          drect.MinY = yoff - HEIGHT;
  793.          drect.MaxY = yoff;
  794.  
  795.          if ( ! (new_region = NewRegion())) return;
  796.  
  797.          if ( ! (OrRectRegion(  new_region, &frect))) return;
  798.          if ( ! (XorRectRegion( new_region, &drect))) return;
  799.  
  800.          if (( old_region = InstallClipRegion( PlotWindowWnd-> WLayer, new_region ))) return;
  801.     
  802.         EraseRect( rp, 0, 0, PlotWindowWnd-> Width, PlotWindowWnd-> Height);
  803.  
  804.          new_region = InstallClipRegion(PlotWindowWnd->WLayer, old_region);
  805.  
  806.          DisposeRegion(new_region);
  807.       }
  808.     else
  809.         SetRast( rp, 0);
  810.  
  811.      if ( CPANEL ) RefreshGadgets( PlotWindowGadgets[0], PlotWindowWnd, NULL);
  812.  
  813. }
  814.  
  815. /* Draw an XAxis tik and put text if major */
  816.  
  817. void ticX ( double val, BOOL major)
  818. {
  819. LONG x, y;
  820. UBYTE tx[32];
  821. UBYTE *txp;
  822. UBYTE fm[32];
  823. double rs;
  824. struct TextExtent txex;
  825.  
  826.      x = ScaleX((double) val);
  827.      y = yoff + 3;
  828.      Move ( rp, x, y);
  829.      txp = tx;
  830.  
  831.      if ( major )
  832.           y += SIZETIC;
  833.      else
  834.           y += SIZETIC/2;
  835.  
  836.      SetDrMd( rp, JAM2);
  837.      SetBPen(rp,0);
  838.      SetAPen( rp, ( MONO ? 1 : TIKCOLOR));
  839.  
  840.      Draw( rp, x, y);
  841.  
  842.      if ( major )
  843.        {
  844.           if ( cv.xmode == 1 )
  845.             {
  846.                rs = val / cv.xfact;
  847.                Round( &rs );
  848.                sprintf( tx, "%lg", rs);
  849.             }
  850.           else if ( cv.xmode == 0 )
  851.             {
  852.                sprintf( fm, "%%.%hdlf", cv.xprec);
  853.                sprintf( tx, fm, val);
  854.             }
  855.           else if ( cv.xmode == -1 )
  856.             {
  857.                sprintf( tx, "%le", val);
  858.                E2xTen( tx );
  859.                txp++;
  860.             }
  861.  
  862.           TextExtent( rp, txp, strlen( txp ), &txex);
  863.           Move ( rp, x - txex.te_Width/2, y + txex.te_Height + SIZETIC / 2 );
  864.           Text( rp, txp, strlen( txp ));
  865.        }
  866.  
  867. }
  868.  
  869. /* Draw a YAxis tik and put text if major */
  870.  
  871. void ticY ( double val, BOOL major)
  872. {
  873. LONG x, y;
  874. UBYTE tx[32];
  875. UBYTE *txp;
  876. UBYTE fm[32];
  877. double rs;
  878. struct TextExtent txex;
  879.  
  880.      y = ScaleY((double) val);
  881.      x = xoff - 3;
  882.      Move ( rp, x, y);
  883.      txp = tx;
  884.  
  885.      if ( major )
  886.           x -= SIZETIC;
  887.      else
  888.           x -= SIZETIC/2;
  889.  
  890.      SetDrMd( rp, JAM2);
  891.      SetBPen( rp, 0);
  892.      SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  893.  
  894.      Draw( rp, x, y);
  895.  
  896.      if ( major )
  897.        {
  898.           if ( cv.ymode == 1 )
  899.             {
  900.                rs = val / cv.yfact;
  901.                Round( &rs );
  902.                sprintf( tx, "%lg", rs);
  903.             }
  904.           else if ( cv.ymode == 0 )
  905.             {
  906.                sprintf( fm, "%%.%hdlf", cv.yprec);
  907.                sprintf( tx, fm, val);
  908.             }
  909.           else if ( cv.ymode == -1 )
  910.             {
  911.                sprintf( tx, "%le", val);
  912.                E2xTen( tx );
  913.                txp++;
  914.             }
  915.  
  916.  
  917.           TextExtent(rp, txp, strlen( txp ), &txex);
  918.           Move( rp, x - txex.te_Width - SIZETIC / 2, y + txex.te_Height/2 - 1);
  919.           Text( rp, txp, strlen( txp ));
  920.        }
  921. }
  922.  
  923. /* Routine does everything when Zoom gadget selected */
  924.  
  925. void Zoom()
  926. {
  927. BOOL   running = TRUE;
  928. BOOL   select = FALSE;
  929. LONG   j = 0, k = 0;
  930. WORD   selco[2];
  931. static WORD Cross [2];
  932. struct IntuiMessage *m;
  933. double a,b,c,d;
  934.  
  935.      ReportMouse( TRUE, PlotWindowWnd);
  936.      SetMouseQueue( PlotWindowWnd, 1 );
  937.      do {
  938.  
  939.        Wait ( 1L << PlotWindowWnd-> UserPort-> mp_SigBit );
  940.  
  941.        while( m = GT_GetIMsg( PlotWindowWnd->UserPort )) {
  942.  
  943.           CopyMem(( char * )m, ( char * )&PlotWindowMsg, (long)sizeof( struct IntuiMessage ));
  944.  
  945.           GT_ReplyIMsg( m );
  946.  
  947.           switch ( PlotWindowMsg.Class ) {
  948.  
  949.                case IDCMP_MOUSEMOVE:
  950.  
  951.                     if ( PlotWindowMsg.MouseX > xoff && PlotWindowMsg.MouseX < xoff + WIDTH
  952.                          && PlotWindowMsg.MouseY < yoff && PlotWindowMsg.MouseY > yoff - HEIGHT)
  953.                       {
  954.                          SetDrMd( rp, COMPLEMENT);
  955.  
  956.                          if ( k )
  957.                            {
  958.                               Move( rp, xoff, Cross[1]);
  959.                               Draw( rp, xoff + WIDTH, Cross[1]);
  960.  
  961.                               Move( rp, Cross[0], yoff);
  962.                               Draw( rp, Cross[0], yoff - HEIGHT);
  963.                            }
  964.  
  965.  
  966.                          Move( rp, xoff, PlotWindowMsg.MouseY);
  967.                          Draw( rp, xoff + WIDTH, PlotWindowMsg.MouseY);
  968.  
  969.                          Move( rp, PlotWindowMsg.MouseX, yoff);
  970.                          Draw( rp, PlotWindowMsg.MouseX, yoff - HEIGHT);
  971.  
  972.                          if ( select )
  973.                            {
  974.                               if ( j )
  975.                                 {
  976.                                    Move( rp, selco[0], selco[1]);
  977.                                    Draw( rp, selco[0], Cross[1]);
  978.                                    Move( rp, selco[0], selco[1]);
  979.                                    Draw( rp, Cross[0], selco[1]);
  980.                                 }
  981.  
  982.                               Move( rp, selco[0], selco[1]);
  983.                               Draw( rp, selco[0], PlotWindowMsg.MouseY);
  984.                               Move( rp, selco[0], selco[1]);
  985.                               Draw( rp, PlotWindowMsg.MouseX, selco[1]);
  986.  
  987.                               j++;
  988.                            }
  989.  
  990.                          Cross[0] = PlotWindowMsg.MouseX;
  991.                          Cross[1] = PlotWindowMsg.MouseY;
  992.  
  993.                          k++;
  994.                       }
  995.  
  996.                     break;
  997.  
  998.                case IDCMP_MOUSEBUTTONS:
  999.                     if (PlotWindowMsg.Code == SELECTUP) running = FALSE;
  1000.                     else if (PlotWindowMsg.Code == SELECTDOWN)
  1001.                       {
  1002.                          select = TRUE;
  1003.                          selco[0] = PlotWindowMsg.MouseX;
  1004.                          selco[1] = PlotWindowMsg.MouseY;
  1005.  
  1006.                       }
  1007.                     break;
  1008.  
  1009.                case IDCMP_VANILLAKEY:
  1010.  
  1011.                               if ( k )
  1012.                                 {
  1013.                                    Move( rp, xoff, Cross[1]);
  1014.                                    Draw( rp, xoff + WIDTH, Cross[1]);
  1015.  
  1016.                                    Move( rp, Cross[0], yoff);
  1017.                                    Draw( rp, Cross[0], yoff - HEIGHT);
  1018.                                    goto end;
  1019.                                 }
  1020.  
  1021.                default:
  1022.                     break;
  1023.           }
  1024.        }
  1025.      } while ( running);
  1026.  
  1027.         SetPointer( PlotWindowWnd, WAITPointer, WAITHEIGHT, WAITWIDTH, WAITXOFF , WAITYOFF);    /* Set pointer cross for zoom */
  1028.      
  1029.      if ( selco[0] == PlotWindowMsg.MouseX || selco[1] == PlotWindowMsg.MouseY )
  1030.        {
  1031.          ReportMouse( FALSE, PlotWindowWnd);
  1032.           DrawView( FALSE );
  1033.           return;
  1034.        }
  1035.      if ( select )
  1036.        {
  1037.           a = ZoomX( selco[0] );
  1038.           b = ZoomX( PlotWindowMsg.MouseX );
  1039.           c = ZoomY( selco[1] );
  1040.           d = ZoomY( PlotWindowMsg.MouseY );
  1041.  
  1042.           cv.xmin = min( a, b);
  1043.           cv.xmax = max( a, b);
  1044.  
  1045.           cv.ymin = min( c, d);
  1046.           cv.ymax = max( c, d);
  1047.  
  1048.           cv.xdelta = cv.xmax - cv.xmin;
  1049.           cv.ydelta = cv.ymax - cv.ymin;
  1050.  
  1051.          DrawView( FALSE );
  1052.      
  1053.       }
  1054. end:
  1055.  
  1056.       ReportMouse( FALSE, PlotWindowWnd);
  1057.  
  1058. }
  1059.  
  1060. /* When mode is exponential keep in engineering units */
  1061.  
  1062. void CalcMode ( double delta , double *fact )
  1063. {
  1064. UBYTE s[32];
  1065. WORD e;
  1066. WORD j = 0, k = 0;
  1067.  
  1068.      sprintf( s ,"%.0le", delta);
  1069.  
  1070.      while ( s[k] != 'e' ) ++k;
  1071.  
  1072.      sscanf( &s[++k], "%hd", &e);
  1073.  
  1074.      if ( e < 1 )  while( j > e ) j -= 3;
  1075.      else  while( j+1 < e ) j += 3;
  1076.  
  1077.      *fact = pow( 10.0, (double)j );
  1078. }
  1079.  
  1080. /* Change exponetial to X10 */
  1081.  
  1082. void E2xTen( UBYTE *s)
  1083. {
  1084. WORD e;
  1085. WORD k = 0;
  1086.  
  1087.      while ( s[k] != 'e' && s[k] != 'E') ++k;
  1088.  
  1089.      sscanf( &s[++k], "%hd", &e);
  1090.  
  1091.      sprintf( s,"* 10%+hd",e);
  1092. }
  1093.  
  1094. /* Write X and Y to screen when mouse select
  1095.    Erase text if mouse has moved more than 3
  1096.    pixels since seldown */
  1097.  
  1098. void Identify(WORD x, WORD y, BOOL SelDOWN)
  1099. {
  1100. static WORD ox;
  1101. static WORD oy;
  1102. struct TextExtent txex;
  1103. static double zx;
  1104. static double zy;
  1105. UBYTE txt[32];
  1106. UBYTE fmt[8];
  1107.  
  1108.      SetDrMd( rp, COMPLEMENT);
  1109.  
  1110.      if( SelDOWN )
  1111.        {
  1112.           SetDrMd( rp, JAM1);
  1113.           SetAPen(rp,15);
  1114.           WritePixel( rp, x, y);
  1115.           SetAPen(rp,min(12,lastcolor));
  1116.           WritePixel( rp, x+1, y+1);
  1117.           WritePixel( rp, x+1, y-1);
  1118.           WritePixel( rp, x-1, y-1);
  1119.           WritePixel( rp, x-1, y+1);
  1120.  
  1121.           SetAPen(rp,13);
  1122.           WritePixel( rp, x+2, y+2);
  1123.           WritePixel( rp, x+2, y-2);
  1124.           WritePixel( rp, x-2, y-2);
  1125.           WritePixel( rp, x-2, y+2);
  1126.  
  1127.           zx = ZoomX( x );
  1128.           zy = ZoomY( y );
  1129.  
  1130.           SetDrMd( rp, COMPLEMENT);
  1131.        }
  1132.  
  1133.      else if ( (x >= ox - 3 && x <= ox + 3 )  && ( y >= oy - 3 && y <= oy + 3 ))
  1134.        {
  1135.           SetDrMd( rp, JAM1);
  1136.           x = ox;
  1137.           y = oy;
  1138.        }
  1139.      else
  1140.        {
  1141.           x = ox;
  1142.           y = oy;
  1143.        }
  1144.  
  1145.  
  1146.      if (depth > 2)
  1147.           SetAPen(rp,15);
  1148.      else
  1149.           SetAPen(rp,1);
  1150.  
  1151.     sprintf( fmt ,"%%.%ldlG", precision+1);
  1152.      sprintf( txt ,fmt, zx);
  1153.  
  1154.      TextExtent( rp, txt, strlen( txt ), &txex);
  1155.      Move ( rp, x+6, y + txex.te_Height);
  1156.      Text (rp,txt, strlen(txt));
  1157.  
  1158.      sprintf( txt ,fmt, zy);
  1159.  
  1160.      TextExtent( rp, txt, strlen( txt ), &txex);
  1161.      Move ( rp, x+6, y-2 );
  1162.      Text (rp,txt, strlen(txt));
  1163.  
  1164.      ox = x;
  1165.      oy = y;
  1166. }
  1167.  
  1168.  
  1169. int CrossHair()
  1170. {
  1171. LONG   k = 0;
  1172. BOOL  lock = FALSE;
  1173. static WORD Cross [2];
  1174. struct IntuiMessage *m;
  1175. double x, y;
  1176. WORD running = TRUE;
  1177. UBYTE txt[128];
  1178. UBYTE fmt[64];
  1179.  
  1180.     sprintf( fmt ,"Y = %%-%ld.%ldlG   X = %%-%ld.%ldlG", precision+6,precision+1,precision+6,precision+1);
  1181.  
  1182.         SetPointer( PlotWindowWnd, IDPointer, IDWIDTH, IDHEIGHT, IDXOFF , IDYOFF);
  1183.  
  1184.      ReportMouse( TRUE, PlotWindowWnd);
  1185.      SetMouseQueue( PlotWindowWnd, 1 );
  1186.      do {
  1187.  
  1188.        Wait ( 1L << PlotWindowWnd-> UserPort-> mp_SigBit );
  1189.  
  1190.        while( m = GT_GetIMsg( PlotWindowWnd->UserPort )) {
  1191.  
  1192.           CopyMem(( char * )m, ( char * )&PlotWindowMsg, (long)sizeof( struct IntuiMessage ));
  1193.  
  1194.           GT_ReplyIMsg( m );
  1195.  
  1196.           switch ( PlotWindowMsg.Class ) {
  1197.  
  1198.                case IDCMP_MOUSEMOVE:
  1199.  
  1200.                     if ( PlotWindowMsg.MouseX > xoff && PlotWindowMsg.MouseX < xoff + WIDTH
  1201.                          && PlotWindowMsg.MouseY < yoff && PlotWindowMsg.MouseY > yoff - HEIGHT)
  1202.                       {
  1203.                      SetDrMd( rp, COMPLEMENT);
  1204.  
  1205.                          if ( k )
  1206.                            {
  1207.                               Move( rp, xoff, Cross[1]);
  1208.                               Draw( rp, xoff + WIDTH, Cross[1]);
  1209.  
  1210.                               if (!lock)
  1211.                                 {
  1212.                                     Move( rp, Cross[0], yoff);
  1213.                                   Draw( rp, Cross[0], yoff - HEIGHT);
  1214.                                 }
  1215.                            }
  1216.  
  1217.  
  1218.                          Move( rp, xoff, PlotWindowMsg.MouseY);
  1219.                          Draw( rp, xoff + WIDTH, PlotWindowMsg.MouseY);
  1220.                          Cross[1] = PlotWindowMsg.MouseY;
  1221.                       y = ZoomY( Cross[1] );
  1222.  
  1223.                          if (!lock)
  1224.                            {
  1225.                                Move( rp, PlotWindowMsg.MouseX, yoff);
  1226.                              Draw( rp, PlotWindowMsg.MouseX, yoff - HEIGHT);
  1227.                              Cross[0] = PlotWindowMsg.MouseX;
  1228.                           x = ZoomX( Cross[0] );
  1229.                            }
  1230.  
  1231.  
  1232.                          k++;
  1233.                       }
  1234.  
  1235.                     sprintf( txt ,fmt, y , x);
  1236.                     SetWindowTitles( PlotWindowWnd, txt, txt );    
  1237.  
  1238.                     break;
  1239.  
  1240.                case IDCMP_MOUSEBUTTONS:
  1241.                     if (PlotWindowMsg.Code == SELECTDOWN)
  1242.                          Identify( Cross[0], Cross[1], TRUE);
  1243.                     else if (PlotWindowMsg.Code == SELECTUP)
  1244.                          Identify( Cross[0], Cross[1], FALSE);
  1245.                
  1246.                     break;
  1247.  
  1248.                case IDCMP_VANILLAKEY:
  1249.                 switch (PlotWindowMsg.Code)
  1250.                   {  
  1251.                       case 32 : /* hit space */
  1252.                         if (!lock) lock = TRUE;
  1253.                         else lock = FALSE;
  1254.                         break;
  1255.                     default:
  1256.                         running = FALSE;
  1257.                         break;
  1258.                   }
  1259.                 
  1260.                 break;
  1261.  
  1262.                default:
  1263.                    running = FALSE;
  1264.                     break;
  1265.           }
  1266.        }
  1267.      } while ( running);
  1268.  
  1269.  
  1270.      if ( k )
  1271.        {
  1272.              SetDrMd( rp, COMPLEMENT);
  1273.  
  1274.              Move( rp, xoff, Cross[1]);
  1275.              Draw( rp, xoff + WIDTH, Cross[1]);
  1276.  
  1277.              Move( rp, Cross[0], yoff);
  1278.              Draw( rp, Cross[0], yoff - HEIGHT);
  1279.        }
  1280.      
  1281.       ReportMouse( FALSE, PlotWindowWnd);
  1282.  
  1283.     return (1);
  1284. }
  1285.